package javawdw.picture.codec;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;

import javawdw.lang.reflect.Reflect;
import javawdw.picture.api.PictureCodec;
import javawdw.picture.core.DynPicture;
import javawdw.picture.core.Frame;
import javawdw.picture.exception.DecodeException;
import javawdw.picture.exception.EncodeException;
import javawdw.picture.gif.codec.GifDecoder;
import javawdw.picture.gif.codec.GifEncoder;

public class Gif2DynCodec implements PictureCodec<DynPicture> {
	/**
	 * 将给定动态图片DynPicture以GIF编码并写入输出流
	 * 
	 * @param dynPicture
	 *            给定动态图片
	 * @param outputStream
	 *            给定输出流
	 * @throws IOException
	 *             写入输出流异常
	 * @throws EncodeException
	 *             编码失败
	 */
	public void encode(DynPicture dynPicture, OutputStream outputStream)
			throws IOException, EncodeException {
		try {
			GifEncoder gifEncoder = new GifEncoder();
			gifEncoder.loadStream(outputStream);
			List<Frame> frames = dynPicture.getFrames();
			List<Integer> delayTimes = dynPicture.getDelayTimes();
			for (int i = 0; i < frames.size(); i++) {
				Frame frame = frames.get(i);
				int delayTime = delayTimes.get(i);
				try {
					Reflect<Frame> reflect = new Reflect<Frame>(){};
					Field field = reflect.getField("image");
					BufferedImage image = (BufferedImage) field.get(frame);
					gifEncoder.addFrame(image, delayTime);
				} catch (Exception e) {
				}
			}
			gifEncoder.close();
		} catch (IOException e) {
			throw e;
		} catch (Exception e) {
			throw new EncodeException();
		}
	}

	/**
	 * 将给定注入流以GIF解码成DynPicture
	 * 
	 * @param inputStream
	 *            给定输入流
	 * @return 解码得到的DynPicture
	 * @throws IOException
	 *             输入流读取失败
	 * @throws DecodeException
	 *             解码失败
	 */
	public DynPicture decode(InputStream inputStream) throws IOException,
			DecodeException {
		try {
			Reflect<DynPicture> reflect1 = new Reflect<DynPicture>(){};
			DynPicture dynPicture = reflect1.getConstructor().newInstance();
			Field field1 = reflect1.getField("frames");
			Field field2 = reflect1.getField("delayTimes");
			List<Frame> frames = new LinkedList<Frame>();
			List<Integer> delayTimes = new LinkedList<Integer>();
			GifDecoder decoder = new GifDecoder();
			decoder.read(inputStream);
			int n = decoder.getFrameCount();
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					Reflect<Frame> reflect2 = new Reflect<Frame>(){};
					Field field = reflect2.getField("image");
					Frame frame = reflect2.getConstructor().newInstance();
					field.set(frame, decoder.getFrame(i));
					int delayTime = decoder.getDelay(i);
					frames.add(frame);
					delayTimes.add(delayTime);
				}
			}
			field1.set(dynPicture, frames);
			field2.set(dynPicture, delayTimes);
			return dynPicture;
		} catch (Exception e) {
			throw new DecodeException();
		}
	}

	/**
	 * 获得给定DynPicture编码后大小
	 * 
	 * @param dynPicture
	 *            给定动态图片
	 * @return 返回图片大小
	 */
	public long getByteSize(DynPicture dynPicture) throws EncodeException {
		ByteArrayOutputStream byteStream = null;
		try {
			byteStream = new ByteArrayOutputStream();
			this.encode(dynPicture, byteStream);
		} catch (IOException e) {
		} finally {
			try {
				byteStream.close();
			} catch (IOException e) {
			}
		}
		return byteStream.size();
	}
}